package com.centaur0.tags;

import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.SimpleTagSupport;

import com.centaur0.ui.menu.EstruturaMenu;
import com.centaur0.ui.menu.GeneralMenuStyle;
import com.centaur0.ui.menu.Menu;
import com.centaur0.ui.menu.MenuMetaInfo;
import com.centaur0.ui.menu.XmlMenuConfigParser;
import com.centaur0.util.Application;

public class MenuTag extends SimpleTagSupport {
	private static final String JSOBJ_MAPA_MENUS = "jsMapaMenusVar";
	private static final String JSOBJ_DIV_MENUS_HABILITADOS = "divMenusHabilitados";
	public String path;
	public String div_id;
	
	public String getDiv_id() {
		return div_id;
	}

	public void setDiv_id(String div_id) {
		this.div_id = div_id;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	@Override
	public void doTag() throws JspException, IOException {
		ServletContext svlCtx = Application.getHttpApplicationContext();
		File file = new File(svlCtx.getRealPath(path));
		EstruturaMenu em = null;
		try{
			em = XmlMenuConfigParser.parseDoc(file);
		} catch(Exception e){
			throw new JspException(e);
		}
		this.printHtml(em);
	}
	
	private void printHtml(EstruturaMenu em) throws JspException, IOException{
		StringBuilder out = new StringBuilder();
		GeneralMenuStyle gms = em.getGeneralMenuStyle();
		boolean flagInnerCellStyle;
		boolean flagOuterCellStyle;
		boolean flagLabelStyle;
		String outerCellStyleId = gms.getOuterCellStyleId() != null? gms.getOuterCellStyleId(): "";
		out.append("<script>");
			out.append(" var functionOnClick = function(){");
				out.append("eval('funcaoCallBack();');");		
			out.append("};\n");
			out.append(" var ".concat(JSOBJ_MAPA_MENUS).concat(" = {};\n"));
			out.append(String.format(" var %s = new Array();\n", JSOBJ_DIV_MENUS_HABILITADOS));
		out.append("</script>");
		if((flagInnerCellStyle = (gms.getInnerCellStyleId() != null && !gms.getInnerCellStyleId().isEmpty())) |
				(flagLabelStyle = (gms.getLabelStyleId() != null && !gms.getLabelStyleId().isEmpty())) |
				(flagOuterCellStyle = (gms.getOuterCellStyleId() != null && !gms.getOuterCellStyleId().isEmpty()))){
			out.append("<style type='text/css'>\n");
				if(flagInnerCellStyle){
					out.append("\n".concat(gms.getInnerCellStyle()));
				}
				if(flagLabelStyle){
					out.append("\n".concat(gms.getLabelStyle()));
				}
				
				if(flagOuterCellStyle){
					out.append("\n".concat(gms.getOuterCellStyle()));
				}
			out.append("</style>");
		}
		List<Menu> menus = em.getMenus();
		boolean hasInnerMenu = false;
		out.append(String.format("<div style='z-index:1000;' id='%s' class='%s'>\n\t", div_id == null? em.toString().substring(em.toString().indexOf("@")+1): div_id, outerCellStyleId));
			out.append("<table style='border:0px;' id='OBJ_Menu'>\n\t\t");
				out.append("<tr id='OBJ_Menu'>\n\t\t");
				StringBuilder buffer = new StringBuilder("<style type='text/css'>\n");
				MenuMetaInfo metainfo = null;
				for(Menu menu: menus){
					metainfo = new MenuMetaInfo(menu);
					menu.setMetaInfo(metainfo);
					String labelStyleId = "_NENHUM_LABELSTYLE_".concat(menu.toString().substring(menu.toString().indexOf("@")+1));
					String labelStyleClass = "";
					if(menu.getLabelStyleId() != null && !menu.getLabelStyleId().isEmpty()){
						labelStyleClass = menu.getLabelStyleId();
						buffer.append("\n".concat(menu.getLabelStyle()));
					} else if(flagLabelStyle){
						labelStyleClass = gms.getLabelStyleId();
					}
					
					String innerCellStyleId = "_NENHUM_INNERCELLSTYLE".concat(menu.toString().substring(menu.toString().indexOf("@")+1));
					String innerCellStyleClass = "";
					if(menu.getInnerCellStyleId() != null && !menu.getInnerCellStyleId().isEmpty()){
						innerCellStyleClass  = menu.getInnerCellStyleId();
						buffer.append("\n".concat(menu.getInnerCellStyle()));
					} else if(flagInnerCellStyle){
						innerCellStyleClass = gms.getInnerCellStyleId();
					}
					
					out.append("<td style='border:0px;width:auto;' id='OBJ_Menu'>\n\t\t\t");
						out.append(String.format("<div style='position:relative;width:auto;word-wrap:normal;' id='%s' class='%s'>\n\t\t\t\t", innerCellStyleId, innerCellStyleClass));
						metainfo.setParentDivId(innerCellStyleId);
							if(menu.getChildren() != null && menu.getChildren().size() > 0){
								hasInnerMenu = true;
								this.construirInnerMenus(flagLabelStyle, flagInnerCellStyle, out, menu, gms);
							}
							metainfo.setHRefDivId(innerCellStyleId);
							metainfo.setHRefId(labelStyleId);
							if(menu.getLink() != null && menu.getLink().isAjax()){
								this.getJspContext().getOut().append(out.toString());
								out = new StringBuilder();
								AjaxLinkTag tag = new AjaxLinkTag();
								tag.setJspContext(getJspContext());
								tag.setParent(this);
								tag.setAguarde(menu.getLink().getAguarde());
								tag.setDescription(menu.getLabel());
								tag.setFundoEscuro(menu.getLink().getFundoEscuro());
								tag.setHrefId(labelStyleId);
								tag.setHrefClass(labelStyleClass);
								tag.setOuterId(menu.getLink().getOuterId());
								tag.setPath(menu.getLink().getText());
								tag.doTag();
							} else {
								out.append(String.format("<a id='%s' class='%s' href='%s'", labelStyleId, labelStyleClass, (menu.getLink() == null || menu.getLink().getText().isEmpty()? 
										"javascript:;":menu.getLink().getText())).concat(">\n\t\t\t\t\t"));
									out.append("&nbsp;".concat(menu.getLabel()).concat("&nbsp;\n\t\t\t\t"));
								out.append("</a>\n\t\t\t");
							}
						out.append("</div>\n\t\t");
					out.append("</td>\n\t\t");
				}
				buffer.append("\n</style>");
				out.append("</tr>\n\t");
			out.append("</table>\n");
		out.append("</div>\n");
		if(hasInnerMenu){
			out.append("<script>\n");
			
				out.append("function limparMenus(key){\n");
					out.append("if(key != null && key != 'undefined'){\n");
						out.append(String.format("var array = %s[key];\n", JSOBJ_MAPA_MENUS));
						out.append("if(array != null && array != 'undefined'){\n");
							out.append("for(var i = 0; i < array.length; i++){\n");
								out.append("limparMenus(array[i]);\n");
								out.append("document.getElementById(array[i]).style.display = 'none';\n");
							out.append("}\n");
						out.append("}\n");
					out.append("}\n");
				out.append("}\n");
			
				out.append(" var divs  = new Array();\n");
				
				out.append(String.format(" %s[%s.length] = 'OBJ_Menu';\n", JSOBJ_DIV_MENUS_HABILITADOS, JSOBJ_DIV_MENUS_HABILITADOS));
				out.append(" document.onmousemove = function(){\n"); 	
					out.append(String.format(" for(var i in %s){\n", JSOBJ_DIV_MENUS_HABILITADOS));
						out.append(String.format(" if(event.srcElement.id == %s[i]){\n", JSOBJ_DIV_MENUS_HABILITADOS));
							out.append(" return;\n");
						out.append(" }\n");
					out.append(" }\n");
					out.append(" eval('funcaoCallBack();');\n");
				out.append(" };\n");
				out.append("var index = 0;\n");
				out.append("var funcaoCallBack = function(){");
					out.append("if(divs != null && divs.length > 0){");
						out.append("for(i = 0; i < divs.length; i++){");
							out.append("document.getElementById(divs[i]).style.display = 'none';");
						out.append("}\n");
					out.append("}\n");
				out.append("};\n");
				out.append("function adicionarDivParaBloqueio(divId){");
					out.append("if(divs != null && divs.length > 0){");
						out.append("var x = false;\n");
						out.append("for(var i in divs){");
							out.append("if(divs[i] == divId){");
								out.append("x = true;");
								out.append("break;");
							out.append("}\n");
						out.append("}\n");
						out.append("if(!x){");
							out.append("divs[index++] = divId;");
						out.append("}\n");
					out.append("} else divs[index++] = divId;");
				out.append("}\n");
				for(Menu menu: menus){
					appendHtmlIds(out, menu);
					out.append(String.format(" document.getElementById('%s').onclick = functionOnClick;", menu.getMetaInfo().getHrefId()));
					if(menu.getChildren() != null && menu.getChildren().size() > 0){
						out.append(JSOBJ_MAPA_MENUS+"['"+menu.getChildren().get(0).getMetaInfo().getParentDivId()+"'] = "+menu.getMetaInfo().getJsArrayDivFilhos()+";\n");
					}
					boolean flag = menu.getChildren() != null && menu.getChildren().size() > 0;
					out.append(String.format(" document.getElementById('%s').onmouseover = function(){", menu.getMetaInfo().getHrefDivId()));
						if(flag){
							out.append(String.format("var s = '%s';", menu.getChildren().get(0).getMetaInfo().getParentDivId()));
							out.append("if(document.getElementById(s).style.display != 'block'){");
								out.append("limparMenus('root');");
							out.append("}");
						} else{
							out.append("limparMenus('root');");
						}
						if(flag){
							out.append("if(document.getElementById(s).style.display != 'block'){");
								out.append("var href = window.event.srcElement;");
								out.append("document.getElementById(s).style.top  = ((href.offsetTop  +" +
										   " href.offsetHeight)+'px');");
								out.append("document.getElementById(s).style.left = (href.offsetLeft+'px');");
								out.append("document.getElementById(s).style.display = 'block';");
								out.append("adicionarDivParaBloqueio(s);");
							out.append("}");
						}
					out.append("}\n");
				}
				out.append(JSOBJ_MAPA_MENUS.concat("['root'] = "+this.getJsArrayDivFilhos(em)+";"));
			out.append("\n</script>");
		}
		this.getJspContext().getOut().append(out.toString());
		this.getJspContext().getOut().append(buffer.toString());
	}

	private void appendHtmlIds(Appendable out, Menu menu) throws IOException{
		out.append(String.format(" %s[%s.length] = '%s';\n", JSOBJ_DIV_MENUS_HABILITADOS, JSOBJ_DIV_MENUS_HABILITADOS, menu.getMetaInfo().getHrefDivId()));
		out.append(String.format(" %s[%s.length] = '%s';\n", JSOBJ_DIV_MENUS_HABILITADOS, JSOBJ_DIV_MENUS_HABILITADOS, menu.getMetaInfo().getHrefId()));
		out.append(String.format(" %s[%s.length] = '%s';\n", JSOBJ_DIV_MENUS_HABILITADOS, JSOBJ_DIV_MENUS_HABILITADOS, menu.getMetaInfo().getParentDivId()));
		List<Menu> menus;
		if((menus = menu.getChildren()) != null && menus.size() > 0){
			for(Menu menuChild: menus){
				appendHtmlIds(out, menuChild);
			}
		}
	}

	private String getJsArrayDivFilhos(EstruturaMenu em) {
		List<Menu> menus = em.getMenus();
		StringBuilder buffer = new StringBuilder("[");
		for(Menu menu: menus){
			if(menu.getChildren() != null && menu.getChildren().size() > 0){
				buffer.append("'".concat(menu.getChildren().get(0).getMetaInfo().getParentDivId()).concat("',"));
			}
		}
		return buffer.substring(0, buffer.length() - 1).concat("]");
	}

	private void construirInnerMenus(boolean flagLabelStyle, boolean flagInnerCellStyle, 
			StringBuilder out, Menu menuParent, GeneralMenuStyle gms) 
	throws JspException, IOException{
		String parentDivId = menuParent.toString().substring(menuParent.toString().indexOf("@")+1);
		String outerCellStyleId = gms.getOuterCellStyleId() != null? gms.getOuterCellStyleId(): "";
		out.append(String.format("<div align='left' style='position:absolute;display:none;width:auto;z-index:1000;' id='%s' class='%s'>\n\t", parentDivId, outerCellStyleId));
			out.append("<table style='width:auto;' style='border:0px;' id='OBJ_Menu'>\n\t\t");
				StringBuilder buffer = new StringBuilder("<style type='text/css'>\n");
				List<Menu> menus = menuParent.getChildren();
				MenuMetaInfo metainfo = null;
				for(Menu menu: menus){
					out.append("<tr id='OBJ_Menu' style='border:0px;width:auto;'>\n\t\t");
						metainfo = new MenuMetaInfo(menu);
						menu.setMetaInfo(metainfo);
						metainfo.setParentDivId(parentDivId);
						String labelStyleId = "_NENHUM_LABELSTYLE_".concat(menu.toString().substring(menu.toString().indexOf("@")+1));
						String labelStyleClass = "";
						if(menu.getLabelStyleId() != null && !menu.getLabelStyleId().isEmpty()){
							labelStyleClass = menu.getLabelStyleId();
							buffer.append("\n".concat(menu.getLabelStyle()));
						} else if(flagLabelStyle){
							labelStyleClass = gms.getLabelStyleId();
						}
						String innerCellStyleId = "_NENHUM_INNERCELLSTYLE".concat(menu.toString().substring(menu.toString().indexOf("@")+1));
						String innerCellStyleClass = "";
						if(menu.getInnerCellStyleId() != null && !menu.getInnerCellStyleId().isEmpty()){
							innerCellStyleClass  = menu.getInnerCellStyleId();
							buffer.append("\n".concat(menu.getInnerCellStyle()));
						} else if(flagInnerCellStyle){
							innerCellStyleClass = gms.getInnerCellStyleId();
						}
	
						metainfo.setHRefDivId(innerCellStyleId);
						metainfo.setHRefId(labelStyleId);
						out.append("<td style='border:0px;width:auto;' id='OBJ_Menu' nowrap>\n\t\t\t");
							out.append(String.format("<div style='align:left;width:100%%;' id='%s' class='%s'>\n\t\t\t\t", innerCellStyleId, innerCellStyleClass));
								if(menu.getChildren() != null && menu.getChildren().size() > 0){
									this.construirInnerMenus(flagLabelStyle, flagInnerCellStyle, out, menu, gms);
								}
								if(menu.getLink() != null && menu.getLink().isAjax()){
									this.getJspContext().getOut().append(out.toString());
									out.setLength(0);
									AjaxLinkTag tag = new AjaxLinkTag();
									tag.setJspContext(getJspContext());
									tag.setParent(this);
									tag.setAguarde(menu.getLink().getAguarde());
									tag.setDescription(menu.getLabel());
									tag.setFundoEscuro(menu.getLink().getFundoEscuro());
									tag.setHrefId(labelStyleId);
									tag.setHrefClass(labelStyleClass);
									tag.setOuterId(menu.getLink().getOuterId());
									tag.setPath(menu.getLink().getText());
									tag.doTag();
								} else {
									out.append(String.format("<a id='%s' class='%s' href='%s'", labelStyleId, labelStyleClass, (menu.getLink() == null || menu.getLink().getText().isEmpty()? 
											"javascript:;":menu.getLink().getText())).concat(">\n\t\t\t\t\t"));
										out.append("&nbsp;".concat(menu.getLabel()).concat("&nbsp;\n\t\t\t\t"));
									out.append("</a>\n\t\t\t");
								}
								out.append("<script>");
									boolean flag = menu.getChildren() != null && menu.getChildren().size() > 0;
									out.append(String.format(" document.getElementById('%s').onmouseover = function(){", menu.getMetaInfo().getHrefDivId()));
										if(flag){
											out.append(String.format("var s = '%s';", menu.getChildren().get(0).getMetaInfo().getParentDivId()));
											out.append("if(document.getElementById(s).style.display != 'block'){");
												out.append(String.format("limparMenus('%s');", menu.getMetaInfo().getParentDivId()));
											out.append("}");
										} else{
											out.append(String.format("limparMenus('%s');", menu.getMetaInfo().getParentDivId()));
										}
										if(flag){
											out.append("if(document.getElementById(s).style.display != 'block'){");
												out.append("var href = window.event.srcElement;");
												out.append(String.format("var s = '%s';", menu.getChildren().get(0).getMetaInfo().getParentDivId()));
												out.append("document.getElementById(s).style.top  = ((href.offsetParent.offsetTop-2)+'px');");
												out.append("document.getElementById(s).style.left = ((href.offsetLeft + ".concat(
													String.format("document.getElementById('%s').offsetWidth - 2)+'px');", 
															      menu.getMetaInfo().getParentDivId()))
												);
												out.append("document.getElementById(s).style.display = 'block';");
												out.append("adicionarDivParaBloqueio(s);");
											out.append("}");
										}
									out.append("}\n");
									out.append(String.format(" document.getElementById('%s').onclick = functionOnClick;\n", menu.getMetaInfo().getHrefId()));
									if(menu.getChildren() != null && menu.getChildren().size() > 0){
										out.append(JSOBJ_MAPA_MENUS+"['"+menu.getChildren().get(0).getMetaInfo().getParentDivId()+"'] = "+menu.getMetaInfo().getJsArrayDivFilhos()+";");
									}
								out.append("</script>");
							out.append("</div>\n\t\t");
						out.append("</td>\n\t\t");
					out.append("</tr>\n\t");
				}
				buffer.append("\n</style>");
			out.append("</table>\n");
		out.append("</div>\n");
		//out.append("<script>\n");
		//out.append(JSOBJ_MAPA_MENUS+"['"+menuParent.getMetaInfo().getParentDivId()+"'] = "+menuParent.getMetaInfo().getJsArrayDivFilhos()+";");
		//out.append("\n</script>");
		this.getJspContext().getOut().append(buffer.toString());
	}
}
